package com.zhulong.saas.cloud.gateway.oauth2;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;

/**
 * 使用token的认证方式
 */
public class Oauth2TokenAuthenticationManager implements ReactiveAuthenticationManager {

    private ResourceServerTokenServices resourceServerTokenServices;

    public Oauth2TokenAuthenticationManager(ResourceServerTokenServices resourceServerTokenServices) {
        Assert.notNull(resourceServerTokenServices, "resourceServerTokenServices can not be null");
        this.resourceServerTokenServices = resourceServerTokenServices;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        return Mono.justOrEmpty(authentication)
                .filter(a -> a != null && a instanceof BearerTokenAuthenticationToken)
                .cast(BearerTokenAuthenticationToken.class)
                .map(BearerTokenAuthenticationToken::getToken)
                .flatMap(accessToken -> {
                    Authentication authentication1 = resourceServerTokenServices.loadAuthentication(accessToken);
                    if (authentication1 == null) {
                        return Mono.error(new BadCredentialsException("token " + accessToken + " invalid"));
                    }
                    return Mono.just(authentication1);
                });
    }
}
